home *** CD-ROM | disk | FTP | other *** search
- /*
- dshell v3
-
- コマンド行(◎... TYPE=~)の処理
- */
-
- #include "dsh.h"
-
- static void *get_copywk(int *, int);
- static void copy(const uchar *, const uchar *, char);
- static int prepx(uchar *, uchar *);
- static int postx(uchar *);
- static int chk_drvready(char, const char *);
-
-
- /*
- キャラクタデバイスかどうかの確認
- */
- uchar
- isDevice(const char *s)
- {
- int fno, stat;
-
- if ((fno = OPEN(s, 0)) < 0)
- return FALSE;
- stat = IOCTRLGT(fno);
- CLOSE(fno);
-
- return (stat >= 0 && (stat & 0x80));
- }
-
-
- /*
- スクロール範囲の左上ドット座標を得る
- */
- unsigned long getConHome(void)
- {
- unsigned long n;
-
- asm("
- moveq.l #-1,d1
- moveq.l #-1,d2
- moveq.l #$2e,d0 ;_B_CONSOL
- trap #15
- move.l d1,%0
- " : "=g"(n) : : "d0", "d1", "d2");
-
- return n;
- }
-
-
- /*
- TYPE= よりあとの文字列をコマンドとして解釈・実行
- datは TYPE=よりあとを指している
- 例: TYPE=DOC:SAMPLE.DOC
- ^
- datの指している位置
- */
- static short defG;
-
- void
- dtype(const uchar *dat, uchar inMenuFlag)
- {
- uchar *temp;
- uchar *prbf; /* 後処理用情報バッファ */
- static const char GMDSW[] = {'-', '+', '*', '?', }; /* 画面モード切替マーク */
- short g, gm = -1; /* gm:GMODE変化フラグ(変化前保存兼用) */
- uchar noUpdateScreen = FALSE;
- unsigned long typeCommand;
- ushort dexecFlag = 0;
- uchar *p, *q, c;
- uchar f;
- int n;
-
- p = (uchar *)&typeCommand;
- q = dat;
- *p++ = 0;
- *p++ = (*q++ & ~0x20);
- *p++ = (*q++ & ~0x20);
- *p = (*q++ & ~0x20);
- q++; // skip ':'
-
- prbf = NULL;
- if (dat[3] == ';' || dat[3] == ',') {
- long n;
-
- prbf = malloc(POSPMAX);
- if (prbf == NULL) {
- d_heap();
- goto SKIP;
- }
- n = prepx(q, prbf);
- if (n <= 0) {
- free(prbf);
- prbf = NULL;
- if (n < 0)
- goto SKIP; /* 前処理がエラーだった場合、以降の処理を行なわない */
- }
- q += n; /* 前処理を行ない、前処理部分をスキップする */
- }
-
- defG = defGMODE;
- g = -1;
- if (*(q + 1) == ':') {
- g = sizeof(GMDSW) / sizeof(GMDSW[0]);
- while (--g >= 0) {
- if (*q == GMDSW[g]) {
- if (g > 2) {
- if (defG == 0) {
- gm = 0;
- defG++;
- }
- dexecFlag |= DEX_GMODE | DEX_GCLS | DEX_NDIN; ///
- } else if (GMODE != g) {
- gm = GMODE;
- set_g_mode(g);
- dexecFlag |= DEX_NDIN;
- }
- q += 2;
- break;
- }
- }
- }
- if (g < 0 && defG != 0)
- dexecFlag |= DEX_GMODE;
- q += strspn(q, " \t");
-
- switch (typeCommand) {
- case 'EDE':
- /*
- 作業用メモリを確保
- */
- temp = malloc(strlen(q) + 1);
- if (temp == NULL) {
- d_heap();
- break;
- }
-
- /*
- 前半のEXE部分
- */
- dexecFlag |= DEX_SHELL;
- p = temp;
- if (*q == '!') {
- *p++ = *q++;
- dexecFlag |= (DEX_SLNT | DEX_NDIN);
- }
- q += strspn(q, " \t");
- f = FALSE;
- while ((c = *q++) != '\0' && c != ';') {
- *p++ = c;
- if (c != ' ' && c != '\t')
- f = TRUE;
- }
- *p = '\0';
- if (c == '\0')
- q--;
- q += strspn(q, " \t");
- if (*q == '\0' || *q == ';' && *(q + 1) == '\0') {
- q = temp;
- goto postExe;
- }
- if (f) { /* "COMMAND.X" のみなら呼出をパス */
- dexecFlag = dexec(temp, dexecFlag);
- if (GMODE > 0 && (dexecFlag & DEX_NDIN))
- g_push(TRUE);
- } else if (gm >= 0)
- din(FALSE);
-
- /*
- 真中のDOC部分
- */
- p = temp;
- while ((c = *q++) != '\0' && c != ';')
- *p++ = c;
- *p = '\0';
- if (c == '\0')
- q--;
- q += strspn(q, " \t");
- if (*temp != '\0') {
- temp = realloc(temp, strlen(temp) + 1);
- dshell(temp);
- }
-
- /*
- 後半のEXE部分
- */
- dexecFlag &= ~(DEX_SLNT | DEX_NDIN);
- if (gm >= 0)
- dexecFlag |= DEX_NDIN;
- p = q;
- if (*p == '!') {
- dexecFlag |= (DEX_SLNT | DEX_NDIN);
- p++;
- }
- p += strspn(p, " \t");
- f = *p;
- postExe:
- if (f)
- dexecFlag = dexec(q, dexecFlag);
- free(temp);
- break;
- case 'DOC':
- dexecFlag = 0;
- if (gm >= 0)
- din(FALSE);
- dshell(q);
- break;
- case 'EXE':
- dexecFlag = dexec(q, dexecFlag | DEX_WAIT);
- break;
- case 'CLI':
- dexecFlag = dexec(q, dexecFlag | DEX_WAIT | DEX_SHELL);
- break;
- case 'EXS':
- dexecFlag = dexec(q, dexecFlag | DEX_NCLR);
- break;
- case 'COP':
- dexecFlag = 0;
- if (n = dinstrchr(q, ' ')) {
- p = q + n - 1;
- *p++ = '\0';
- copy(q, p, TRUE);
- *--p = ' ';
- } else {
- dabort("コピーのパラメータが異常です");
- }
- noUpdateScreen = TRUE;
- break;
- case 'END':
- setenv_and_export("DSHELLSTAT", q);
- dend();
- break;
- default:
- n = (typeCommand << 8);
- #define deviceName ((uchar *)&n)
- dexecFlag = 0;
- if (isDevice(deviceName)) {
- noUpdateScreen = TRUE;
- if (typeCommand == 'PCM' || typeCommand == 'OPM') {
- if (!inMenuFlag)
- p_execmark(L'♪');
- if (typeCommand == 'PCM') {
- copy(q, deviceName, FALSE);
- if (debugMode && (B_SFTSNS() & (LED_CODEIN | LED_KANA)) == LED_CODEIN)
- w_wait(99);
- } else {
- copy(q, deviceName, TRUE);
- if (debugMode && (B_SFTSNS() & (LED_CODEIN | LED_KANA)) == LED_CODEIN) {
- w_wait(99);
- w_wait(99);
- }
- }
- } else {
- copy(q, deviceName, TRUE);
- }
- } else {
- dabort("指定のデバイスが組み込まれていません");
- }
- break;
- #undef deviceName
- }
-
- if (gm >= 0 && (gm == 0 || GMODE == 0)) {
- set_g_mode(gm);
- din(FALSE);
- noUpdateScreen = FALSE;
- } else if (GMODE > 0 && (dexecFlag & DEX_NDIN)) {
- g_push(TRUE);
- }
- if (GMODE == 0 && resetBgFlag)
- resetBG();
- resetBgFlag = FALSE;
- if (!noUpdateScreen) {
- p_scr();
- p_fpt(1);
- p_time(1);
- }
-
- SKIP:
- if (prbf != NULL) { /* 前処理したなら後処理もする */
- postx(prbf);
- free(prbf);
- }
- w_close();
- }
-
-
- /*
- 外部プログラムを子プロセスとして起動
-
- DEX_WAIT = 実行後、確認のクリックを要求する
- DEX_PSCR = 実行後、画面を描き直す
- DEX_FKON = 実行の間、ファンクション行を有効にする
- DEX_RETM = 実行前、「exit で戻る」旨を表示
- DEX_NCLR = 実行前に、画面を初期化しない
- DEX_NDOUT = DEX_NCLR に同じ
- DEX_NDIN = 実行後に、画面を初期化しない
- DEX_SLNT = コンソールを表示範囲外に切って実行する (DEX_NDOUT の意味を兼ねる)
- DEX_GCLS = 画面を65536色モードに初期化のうえ、クリアする
- DEX_SHELL = COMMAND.X を介して実行する
- */
- ushort
- dexec(const uchar *command, ushort flag)
- {
- static const uchar childShell[] = "COMMAND.X";
- uchar file[300];
- struct COMLINE comlin;
- int adr, mx, my;
- short breakckMod;
- short shiftKeys = 0;
- static uchar scrnMode[] = { 16, 12, 12, };
- char curdirBak[70];
-
- w_open();
- w_load();
-
- if (*command == '!') {
- command++;
- flag |= DEX_SLNT;
- }
- file[255] = '\0';
- if (flag & DEX_SHELL) {
- strcpy(file, childShell);
- strcpy(file + sizeof(childShell) - 1, " ");
- strncpy(file + sizeof(childShell), command, sizeof(file) - sizeof(childShell));
- } else {
- strncpy(file, command, sizeof(file));
- }
- if (file[255] != '\0') // command が長すぎる
- file[0] = '\0';
-
- if (PATHCHK(file, &comlin, NULL) < 0) {
- dabort("実行ファイルが見当たりません");
- din(TRUE);
- return flag;
- }
- adr = LOAD(file, &comlin, NULL);
- if (adr < 0) {
- dabort("ファイルが見つかりません");
- din(TRUE);
- return flag;
- }
-
- shiftKeys = B_SFTSNS();
- mspos(&mx, &my);
- mouse(2);
- breakckMod = BREAKCK(-1);
- LEDMOD(0, 0); // かなキー OFF
- LEDMOD(1, 0); // ローマ字キー OFF
- LEDMOD(2, 0); // コード入力キー OFF
- LEDMOD(6, 0); // 全角キー OFF
- getcwd(curdirBak, sizeof(curdirBak));
-
- if (flag & DEX_GCLS) {
- vsync();
- B_WPOKE(VIDEOR2, 0);
- C_WIDTH(5);
- }
-
- if (flag & DEX_SLNT) {
- B_CONSOL(0, 512, 96 - 1, 31 - 1);
- BREAKCK(0); // Human68k v1.xx の場合は break off 止まり
- BREAKCK(2); // v2.xx 以降の場合は break kill
- } else {
- uchar crtmod = CRTMOD(-1);
-
- B_CONSOL(0, 0, (crtmod == 12) ? 64 - 1 : 96 - 1, 32 - 1);
- if (!(flag & DEX_NCLR)) {
- dout();
- if (crtmod == 12) {
- vsync();
- B_WPOKE(VIDEOR2, 0x1d2f); /* 半透明 TX & GR */
- }
- }
- if (flag & DEX_FKON)
- nouse_fnk();
- }
- if (flag & DEX_RETM)
- B_PRINT("\r\n exit コマンドでDSHELLに戻ります.\r\n");
-
- clr_kbf();
- B_PRINT("");
- B_CUROFF(); // 'B'_CUROFF で間違いありません
- EXECONLY(adr);
- B_WPOKE(CRTCR21, 0x0033); // jpeged.r 対策...
- B_PRINT("");
-
- mouse(4);
- OS_CUROF();
- initKeyBuffer();
- BREAKCK(breakckMod);
- noSetIbitFlag = FALSE;
- if (debugMode) {
- if (shiftKeys & LED_CODEIN) {
- LEDMOD(2, !(codein_on()));
- if (shiftKeys & LED_KANA)
- LEDMOD(0, 1);
- if (shiftKeys & LED_ROMA)
- LEDMOD(1, 1);
- if (shiftKeys & LED_INS)
- LEDMOD(4, 1);
- }
- if (shiftKeys & LED_ZENKAKU)
- LEDMOD(6, 1);
- }
- CHGDRV((*curdirBak & 0x1f) - 1);
- CHDIR(curdirBak + 2);
-
- if (flag & DEX_WAIT) {
- if ((ushort)getConHome() >= 512 - 16) {
- B_CONSOL(0, 16, 128 - 1, 30 - 1);
- cls();
- }
- w_wait2();
- }
-
- if (flag & DEX_GMODE) {
- ushort r20 = B_WPEEK(CRTCR20);
-
- switch (r20) {
- case 0x300:
- case 0x301:
- case 0x305:
- case 0x310:
- case 0x311:
- case 0x315:
- GMODE = 1;
- break;
- case 0x316:
- GMODE = 2;
- break;
- default:
- GMODE = defG;
- break;
- }
- }
-
- use_fnk();
- if (!(flag & DEX_NDIN) || (uchar)(CRTMOD(-1)) != scrnMode[GMODE]) {
- din(TRUE);
- flag &= ~DEX_NDIN;
- } else {
- mouse(0);
- mouse(4);
- B_COLOR(3);
- B_CONSOL(0, 0, 128 - 1, 64 - 1);
- initPalet();
- clr_kbf();
- }
- msarea(0, 0, GWIDTH - 1, 511);
- setmspos(mx, my);
-
- if (flag & DEX_PSCR) {
- p_scr();
- p_fpt(1);
- p_time(1);
- }
-
- return flag;
- }
-
-
- /*
- copy():コピーのためのワークを確保(MALLOC())
- */
- static void *
- get_copywk(int *mem, int flen)
- {
- int p;
-
- *mem = flen;
- p = MALLOC(*mem);
- if (p > 0) {
- return (void *)p;
- }
- *mem = 8*1024;
- p = MALLOC(*mem);
- if (p > 0) {
- return (void *)p;
- }
- *mem = 1024;
- p = MALLOC(*mem);
- if (p > 0) {
- return (void *)p;
- }
- return NULL;
- }
-
- static void
- copy(const uchar *file1, const uchar *file2, char winFlag)
- {
- int fni, fno;
- char *ptr;
- int mem;
- int flen;
- int n, l;
- int a;
- int nf = 0;
-
- if (winFlag) {
- w_open();
- w_copy();
- }
- fni = open(file1, O_RDONLY | O_BINARY);
- if (fni < 0) {
- dabort("ファイルが見つかりません");
- // w_close();
- return;
- }
- if ((flen = dfilelength(fni)) < 0) {
- dabort("ファイルの長さが得られません");
- close(fni);
- // w_close();
- return;
- }
- fno = open(file2, O_WRONLY | O_BINARY | O_TRUNC);
- if (fno < 0) {
- fno = open(file2, O_WRONLY | O_BINARY | O_TRUNC | O_CREAT, O_RDWR);
- if (fno < 0) {
- dabort("コピー先がオープン出来ません");
- close(fni);
- // w_close();
- return;
- }
- }
- ptr = get_copywk(&mem, flen);
- if (ptr == NULL) {
- d_mem();
- goto EXIT; /* fclose()を一括する為ヨン */
- }
-
- n = flen / mem;
- l = flen % mem;
- for (a = 0; a < n; a++) {
- if (read(fni, ptr, mem) != mem) {
- d_read();
- nf = 1;
- break;
- }
- if (write(fno, ptr, mem) != mem) {
- d_write();
- nf = 1;
- break;
- }
- }
- if (!nf & l) {
- if (read(fni, ptr, l) != l) {
- d_read();
- } else if (write(fno, ptr, l) != l) {
- d_write();
- }
- }
- if (MFREE(ptr)) {
- d_mfree();
- }
-
- EXIT:
- close(fno);
- close(fni);
- // w_close();
- }
-
-
- /*
- TYPE=xxx;~~:... の~~部分(前処理)を処理する
- datp: ~~ の先頭を指すポインタ
- 戻り値: length("~~")+1 (戻り先でdatpに足すと':'の次からを指して都合いいので)
- ただし戻り値が-1だった場合、エラーなので戻り先での処理は中断する。
-
-
- (前処理のセパレータを '=' の他 ' ' も許すことにした)
-
- CD=xxx : 実行前にカレントパス移動。終了後パスを戻す。
- xxx にドライブ指定があった場合、
- カレントドライブ移動+パス移動、
- 後処理はパスを戻す+カレントドライブを戻す
-
- 移動先のドライブがnot readyだった場合は待つ。
- 右クリックされたら待ち中止。
-
- CK=n n = 'A' ~ 'Z'
- そのドライブが準備OKかどうかチェックする。
- 準備できてない場合は待つ。
- 右クリックで中断。
-
-
- posp[] に後処理のための情報を入れて戻す
- (現時点では(ドライブ移動があれば移動前のドライブ名("A:"など)+)変更前のカレントパス)
-
- v3.30
- CD= でも CK= でもなければ、CD= が省略されているものと見なすようにした
- */
- static int
- prepx(uchar *datp, uchar *posp)
- {
- int len = -1;
- uchar buffer[EXLEN];
- uchar posp2[4]; // 'A:',0 が収まれば十分
- uchar tmpbf[80];
-
- *posp = '\0';
- *posp2 = '\0';
-
- if ((datp[0] | 0x20) == 'c' && (datp[1] | 0x20) == 'k'
- && (datp[2] == '=' || datp[2] == ' ')) {
- if (datp[4] == ':' && isalpha(datp[3])) {
- len = 5;
- if (chk_drvready(*(datp + 3), "CHECKDRV:")) {
- wait_mb_off();
- w_open();
- w_mes(0, "CHECKDRV:");
- w_mes(2, "処理を中断します");
- w_wait(150);
- // w_close();
- goto ABORT;
- }
- }
- } else {
- uchar *bufp = buffer;
- uchar *datpBak = datp;
-
- if ((datp[0] | 0x20) == 'c' && (datp[1] | 0x20) == 'd'
- && (datp[2] == '=' || datp[2] == ' '))
- datp += 3;
- if (datp[1] == ':' && isalpha(datp[0])) {
- int drv;
- if (chk_drvready(*datp, "CHGDRV:")) {
- wait_mb_off();
- w_open();
- w_mes(0, "CHGDRV:");
- w_mes(2, "処理を中断します");
- w_wait(150);
- // w_close();
- goto ABORT;
- }
- sprintf(posp2, "%c:", CURDRV() + 'A'); /* 後処理用に現ドライブを得る */
- drv = (*datp & 0x1f) - 1;
- if (CHGDRV(drv) < drv) {
- w_open();
- sprintf(tmpbf, "ドライブ %C: への移動に失敗しました", *datp);
- w_mes(0, "CHGDRV:");
- w_mes(1, tmpbf);
- w_mes(2, "処理を中断します");
- w_wait(200);
- // w_close();
- *posp = '\0';
- goto ABORT;
- }
- *bufp++ = *datp++;
- *bufp++ = *datp++;
- }
- len = dinstrchr(datp, ':');
- if (len <= 0 || len > EXLEN - 3) {
- w_open();
- w_mes(0, "CHDIR:");
- w_mes(1, "記述が異常です(':'が無い)");
- w_mes(2, "処理を中断します");
- w_wait(200);
- // w_close();
- goto ABORT;
- }
- strncpy(bufp, datp, len - 1);
- *(bufp + len - 1) = '\0';
- len += (datp - datpBak);
-
- w_open();
- sprintf(tmpbf, "%s に移動します", buffer);
- w_mes(0, "CHDIR:");
- w_mes(1, tmpbf);
- w_wait(20); /* 最高0.2秒表示 */
- // w_close();
-
- if (getcwd(posp, POSPMAX) == NULL) {
- w_open();
- w_mes(0, "エラー:dtype.c(POSPMAXの不足)");
- w_wait(300); /* 最高3秒待つ */
- // w_close();
- if (*posp2) {
- strcpy(posp, ".;");
- strcat(posp, posp2);
- }
- goto ABORT;
- }
- if (chdir(buffer)) {
- w_open();
- w_mes(0, "パスが移動できませんでした");
- w_mes(2, "処理を中断します");
- w_wait(100); /* 最高1秒待つ */
- // w_close();
- if (*posp2) {
- strcpy(posp, ".;");
- strcat(posp, posp2);
- }
- goto ABORT;
- }
- if (*posp2) {
- strcat(posp, ";");
- strcat(posp, posp2);
- }
- #if 0
- } else { /* default */
- sprintf(tmpbf, "<%.*s>", strcspn(datp, ":"), datp);
- w_open();
- w_mes(0, "現在未対応の処理です");
- w_mes(1, tmpbf);
- w_mes(2, "なにもしないまま処理を続けます");
- w_wait(200); /* 最高2秒待つ */
- // w_close();
- *posp = '\0';
- #endif
- }
-
- posp = realloc(posp, strlen(posp) + 1);
- return len;
-
- ABORT:
- if (*posp != '\0')
- postx(posp);
- return -1;
- }
-
- /*
- 後処理
- 今んとこ後処理の必要なprepxがchdrv・chdirだけなんで、
- ここの処理もカレントドライブ・パスを戻すだけ
- */
- static int
- postx(uchar *posp)
- {
- int sep, ret, drv;
-
- if (*posp == '\0') {
- return 0;
- }
-
- sep = dinstrchr(posp, ';');
- if (sep) {
- posp[sep - 1] = '\0';
- }
-
- if (chdir(posp)) {
- w_open();
- w_mes(0, "カレントパスを戻せませんでした");
- w_mes(2, "パスを戻さないまま処理を続けます");
- w_wait(300); /* 最高3秒待つ */
- // w_close();
- ret = -1;
- } else {
- #if 0
- w_open();
- w_mes(0, "CHDIR:");
- w_mes(1, "パスを移動前に戻しました");
- w_wait(20); /* 0.2秒表示 */
- // w_close();
- #endif
- ret = 0;
- }
-
- if (sep) {
- drv = (posp[sep] & 0x1f) - 1;
- if (CHGDRV(drv) < drv) {
- w_open();
- w_mes(0, "カレントドライブを戻せませんでした");
- w_mes(2, "ドライブを戻さないまま処理を続けます");
- w_wait(300);
- // w_close();
- ret = -1;
- } else {
- #if 0
- w_open();
- w_mes(0, "CHGDRV:");
- w_mes(1, "ドライブを移動前に戻しました");
- w_wait(20);
- // w_close();
- #endif
- }
- }
-
- return ret;
- }
-
-
-
- /*
- 指定ドライブ('A'~'Z')の準備ができていなかったら、
- 準備を促すメッセージを出して準備待ちする。
- 右クリックで中断。
-
- 戻り値:0 OK
- 1 中断
- */
- static int
- chk_drvready(char drv, const char *msg)
- {
- if (!drvready(drv)) {
- char bf[96];
- w_open();
- sprintf(bf, "ドライブ %C: の準備ができていません", drv);
- w_mes(0, msg);
- w_mes(1, bf);
- w_mes(2, "ドライブの用意をして下さい(右クリックで中止)");
- while (!drvready(drv)) {
- int dmx, dmy, bl, br;
- dmsstat(&dmx, &dmy, &bl, &br);
- if (br) {
- wait_mb_off();
- w_close();
- return 1;
- }
- }
- }
-
- return 0;
- }
-